package model;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

/**
 *
 * @author Dustin
 */
public class SortSweep {
    private Heap h;

    /**
     * Genereert array met grootte tapeSize met arrays van grootte H uit megegeven array
     * TapeSize wordt bepaald door lengte van meegeleverde array te delen door H
     * @param data
     * @param H grootte van de heap
     * @return
     */
    private int[][] getRuns(int[] data, int H) {
        int tapeSize = (int) Math.ceil((double)data.length/(double)H);
        int[][] runs = new int[tapeSize][H];
        int index = 0;
        for(int i = 0; i < tapeSize; i++) {
            for(int j = 0; j < H; j++, index++) {
                runs[i][j] =  index < data.length ? data[index] : -1;
            }
        }
        return runs;
    }

    /**
     * Genereert uit meegeleverde array een array met gesorteerde runs van grootte H
     * Bepaalde informatie van deze runs worden hierna uitgeschreven
     * @param data
     * @param H
     * @return
     */
    public int[][] doSortSweep(int[] data, int H) {
        int[][] runs = getRuns(data, H);
        for(int i = 0; i < runs.length; i++) {
            h = new Heap(runs[i]);
            h.buildHeap();
            //h.heapSort();
        }
        write("results.txt", data.length, H, runs);
        return runs;
    }

    /**
     * Schrijft bepaalde informatie over een sorteer slag naar een bestand met naam fileNaam
     * @param fileName
     * @param N
     * @param H
     * @param runs
     */
    public void write(String fileName, int N, int H, int[][] runs) {
        try {
            PrintStream p = new PrintStream(new FileOutputStream(fileName));
            p.println("Aantal gegenereerde getallen: " + N + "\n");
            p.println("Heap grootte: " + H + "\n");
            p.println("Aantal runs: " + runs.length + "\n");
            p.println();
            for(int i = 0; i < runs.length; i++) {
                double average = getAverage(runs[i]);
                p.println("Gemiddelde run " + (i + 1) + ": " + average + "\n");
                p.println("Standaard deviatie run " + (i + 1) + ": " + getDeviation(average, runs[i]) + "\n");
                p.println();
            }

            p.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Genereert het gemiddelde van het meegeleverde array van getallen
     * @param run
     * @return
     */
    private double getAverage(int[] run) {
        double average = 0.0;
        for(int i = 0; i < run.length; i++) {
            average += run[i];
        }
        average /= run.length;
        return average;
    }

    /**
     * Genereert de standaard deviatie van het meegeleverde array van getallen
     * @param average
     * @param run
     * @return
     */
    private double getDeviation(double average, int[] run) {
        double deviation = 0.0;
        for(int i = 0; i < run.length; i++) {
            deviation += Math.pow((average - run[i]), 2);
        }
        deviation = Math.sqrt(deviation / run.length);
        return deviation;
    }
}
